﻿using MahApps.Metro.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor
{
    /// <summary>
    /// ReplaceWithNumberWindow.xaml 的交互逻辑
    /// </summary>
    public partial class ReplaceWithNumberWindow : MetroWindow
    {
        public ReplaceWithNumberWindow()
        {
            InitializeComponent();
        }

        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            this.Hide();
        }

        private void btnReplace_Click(object sender, RoutedEventArgs e)
        {
            var activeEditor = Globals.MainWindow.ActivedEditor;
            if (activeEditor == null) return;

            cmbFindText.Items.Insert(0, cmbFindText.Text);

            int start;
            int step;
            int end;

            if (int.TryParse(FormatText(tbxStartNumber.Text), out start) == false)
            {
                LMessageBox.Show($"起始编号必须是整数，且不能大于等于 {int.MaxValue} ，也不能小于等于 {int.MinValue} ！");
                return;
            }

            var stepText = FormatText(tbxStepNumber.Text);
            if (string.IsNullOrWhiteSpace(stepText))
            {
                step = 1;//默认值为1。
            }
            else
            {
                if (int.TryParse(stepText, out step) == false)
                {
                    LMessageBox.Show("步长值必须是整数！默认值为 1 。");
                    return;
                }
            }

            var endText = FormatText(tbxEndNumber.Text);
            if (string.IsNullOrWhiteSpace(endText))
            {
                if (step > 0) end = int.MaxValue;
                else if (step < 0) end = int.MinValue;
                else
                {
                    if (int.TryParse(endText, out end) == false)
                    {
                        LMessageBox.Show($"结束编号必须是整数！默认值为空，表示最大可能值 {int.MaxValue}。");
                        return;
                    }
                }
            }
            else
            {
                if (int.TryParse(endText, out end) == false)
                {
                    LMessageBox.Show($"结束编号必须是整数！默认值为空，表示最大可能值 {int.MaxValue}。");
                    return;
                }

                if (step > 0)
                {
                    //step为正时，结束编号必须大于起始编号
                    if (end <= start)
                    {
                        LMessageBox.Show($"步长值为正时，结束编号必须大于起始编号。");
                        return;
                    }
                }
                else if (step < 0)
                {
                    //步长值为负时，结束编号必须小于起始编号
                    if (end >= start)
                    {
                        LMessageBox.Show($"步长值为负时，结束编号必须小于起始编号。");
                        return;
                    }
                }
                //步长为0时结束编号无意义。
            }

            RegexOptions options = RegexOptions.None;
            options |= RegexOptions.IgnoreCase;
            options |= RegexOptions.Multiline;

            var regex = new Regex(cmbFindText.Text, options);

            var matches = regex.Matches(activeEditor.EditorBase.Text);
            List<LMatchItem> matchItems = new List<LunarMarkdownEditor.LMatchItem>();
            int currentNumber = start;
            foreach (Match match in matches)
            {
                if (step == 0)
                {
                    string replaceText = $"{currentNumber}.{match.Value}";
                    matchItems.Add(new LMatchItem()
                    {
                        Match = match,
                        ReplaceText = replaceText,
                    });//步长为0时，没有什么实用意义，但逻辑上可以自洽。
                }
                else if (step > 0)
                {
                    string replaceText = $"{currentNumber}.{match.Value}";
                    if (currentNumber > int.MaxValue - step || currentNumber >= end)
                    {
                        currentNumber = start;
                    }
                    else currentNumber += step;


                    matchItems.Add(new LMatchItem()
                    {
                        Match = match,
                        ReplaceText = replaceText,
                    });
                }
                else if (step < 0)
                {
                    string replaceText = $"{currentNumber}.{match.Value}";
                    if (currentNumber < int.MinValue - step || currentNumber <= end)
                    {
                        currentNumber = start;
                    }
                    else currentNumber += step;

                    matchItems.Add(new LMatchItem()
                    {
                        Match = match,
                        ReplaceText = replaceText,
                    });
                }
            }

            activeEditor.EditorBase.BeginChange();
            bool replaceInSelectedText = (activeEditor.EditorBase.SelectionLength > 0);
            int selStartIndex = activeEditor.EditorBase.SelectionStart;
            int selEndIndex = activeEditor.EditorBase.SelectionStart + activeEditor.EditorBase.SelectionLength;

            for (int i = matchItems.Count - 1; i >= 0; i--)
            {
                var item = matchItems[i];
                if (replaceInSelectedText)
                {
                    if (item.Match.Index < selStartIndex) continue;
                    if (item.Match.Index + item.Match.Length > selEndIndex) continue;
                }
                activeEditor.EditorBase.Document.Replace(item.Match.Index, item.Match.Length, item.ReplaceText);
            }
            activeEditor.EditorBase.EndChange();
        }

        private string FormatText(string src)
        {
            if (string.IsNullOrWhiteSpace(src)) return "";

            return src.Trim(new char[] { ' ', '　', '\t' })
                .Replace('０', '0')
                .Replace('１', '1')
                .Replace('２', '2')
                .Replace('３', '3')
                .Replace('４', '4')
                .Replace('５', '5')
                .Replace('６', '6')
                .Replace('７', '7')
                .Replace('８', '8')
                .Replace('９', '9');
        }
    }

    internal class LMatchItem
    {
        public Match Match { get; set; }
        public string ReplaceText { get; set; }
    }

}
